/*
 * Copyright (c) 2010, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "alkes/graph/Visual.h"

namespace alkes {

//#define AL_TRACE_UPDATE_NODE

#if defined(AL_TRACE_UPDATE_NODE)
#define DO_UPDATE() AL_PRINT_NODE(" update")
#else
#define DO_UPDATE() do{}while(0)
#endif
#if defined(AL_TRACE_RENDER_NODE)
#define DO_RENDER() AL_PRINT_NODE(" render")
#else
#define DO_RENDER() do{}while(0)
#endif


Visual::Visual()
: rect_(Rect::ZERO)
{
    setSystemFlag(FLAG_DRAWABLE);
    setSystemFlag(FLAG_HAS_SIZE);
}

void Visual::setConstant(bool is_constant)
{
    if (is_constant)
    {
        setSystemFlag(FLAG_CONSTANT);
        denyModify();
    }
    else
    {
        clearSystemFlag(FLAG_CONSTANT);
        allowModify();
    }
}

void Visual::setRect(const Rect& rect)
{
    setSize(URectSize(rect));
    setDest(UPoint2D(rect));
}

void Visual::setSize(const RectSize& size)
{
    bool modified;

    modified = setProperty(rect_.width, size.width);
    modified = setProperty(rect_.height, size.height) | modified;

    if (modified)
        onResize();
}

void Visual::setDest(const Point2D& dest)
{
    setProperty(rect_.x, dest.x);
    setProperty(rect_.y, dest.y);
}

const Rect& Visual::getRect() const
{
    return rect_;
}

const RectSize Visual::getSize() const
{
    RectSize size = {rect_.width, rect_.height};
    return size;
}

const Point2D Visual::getDest() const
{
    Point2D dest = {rect_.x, rect_.y};
    return dest;
}

bool Visual::isNullDest() const
{
    return rect_.x == 0 && rect_.y == 0;
}

bool Visual::update(UpdateContext& uc)
{
    if (isConstant())
        return uc.relayDirtyFlag(false);

    DO_UPDATE();
    bool dirty = onUpdate(uc);
    clearSystemFlag(FLAG_UPDATING);

    // relay dirty flag to parent.
    return dirty;
}

void Visual::render(GraphicsContext& gc)
{
    if (!isVisible())
        return ;

    DO_RENDER();
    onRender(gc);

    setDirty(false);
}

bool Visual::onUpdate(UpdateContext& /*uc*/)
{
    return isDirty();
}

void Visual::onResize()
{
}

}

